package cn.lg.soar.boot.fc.service.impl;

import cn.lg.soar.boot.fc.entity.*;
import cn.lg.soar.boot.fc.entity.bo.BuildingBo;
import cn.lg.soar.boot.fc.entity.importExcel.BuildingIo;
import cn.lg.soar.boot.fc.entity.vo.BuildingEasyVo;
import cn.lg.soar.boot.fc.entity.vo.BuildingVo;
import cn.lg.soar.boot.fc.entity.vo.CampusEasyVo;
import cn.lg.soar.boot.fc.entity.vo.FcStatisticsVo;
import cn.lg.soar.boot.fc.service.BuildingTypeService;
import cn.lg.soar.boot.fc.service.CampusService;
import cn.lg.soar.boot.fc.tool.BuildingValidation;
import cn.lg.soar.common.data.msg.I18n;
import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.model.PageQuery;
import cn.lg.soar.common.model.PageResult;
import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.common.util.ParameterUtil;
import cn.lg.soar.core.util.easyexcel.ExcelUtil;
import cn.lg.soar.database.query.QueryParams;
import cn.lg.soar.database.query.SqueryWapper;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.lg.soar.database.base.service.impl.BaseServiceImpl;
import cn.lg.soar.boot.fc.mapper.BuildingMapper;
import cn.lg.soar.boot.fc.service.BuildingService;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 楼栋表
 * @author ZhuanZ（无密码）
 * @since 2025-01-10
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Service
public class BuildingServiceImpl extends BaseServiceImpl<BuildingMapper, Building> implements BuildingService {

    @Autowired
    private CampusService campusService;

    @Autowired
    private BuildingTypeService buildingTypeService;

    @Override
    public HttpResult<Serializable> create(BuildingBo buildingBo) {
        ParameterUtil.notNull(buildingBo, "数据不能为空");

        // 效验建账参数是否正确
        if (Objects.isNull(buildingBo.getAccountsSituation()) || !BuildingValidation.checkAccounts(buildingBo.getAccountsSituation())) {
            return HttpResult.fail("4000", "建账参数不正确", "error");
        }

        if (StringUtils.isBlank(buildingBo.getParentId())) {
            return HttpResult.fail("4000", "关联校区信息不为空", "error");
        }

        Building building = new Building();
        BeanUtils.copyProperties(buildingBo, building); // bo 赋值给 entity


        // 父级的参数 关联
        String parentId = buildingBo.getParentId();
        // 祖宗
        String campusIdSearch = "";

        // 1-3-0-0
        String[] searchStr = parentId.split("-");

        if (4 <= searchStr.length) {
            campusIdSearch = !"0".equals(searchStr[0]) ? searchStr[0]: "";
        }

        if (StringUtils.isNotBlank(campusIdSearch)) {
            building.setCampusId(Long.valueOf(campusIdSearch));
        }

        boolean checkFlag =
                StringUtils.isBlank(campusIdSearch);

        if (checkFlag) {
            return HttpResult.fail("4000", "楼栋关联层级不正确，请重新选择", "error");
        }
        // 父级的参数 关联 end


        AssertUtil.isTrue(this.save(building), "创建失败");
        return HttpResult.<Serializable>success("创建成功").setData("success");
    }

    @Override
    public HttpResult<Void> update(BuildingBo buildingBo) {
        ParameterUtil.notNull(buildingBo, "数据不能为空");

        Building building = new Building();
        BeanUtils.copyProperties(buildingBo, building);
        // 父级的参数 关联
        String parentId = buildingBo.getParentId();
        // 祖宗
        String campusIdSearch = "";

        // 1-3-0-0
        String[] searchStr = parentId.split("-");

        if (4 <= searchStr.length) {
            campusIdSearch = !"0".equals(searchStr[0]) ? searchStr[0]: "";
        }

        if (StringUtils.isNotBlank(campusIdSearch)) {
            building.setCampusId(Long.valueOf(campusIdSearch));
        }

        boolean checkFlag =
                StringUtils.isBlank(campusIdSearch);

        if (checkFlag) {
            return HttpResult.fail("4000", "楼栋关联层级不正确，请重新选择", "error");
        }
        // 父级的参数 关联 end

        AssertUtil.isTrue(this.updateById(building), "更新失败");
        return HttpResult.success("更新成功");
    }

    @Override
    public Building getData(Long id) {
        if (Objects.isNull(id)) {
            return new Building();
        }

        Building building = this.getOne(Wrappers.<Building>lambdaQuery().eq(Building::getId, id));
        if (null == building) {
            building = new Building();
        }
        return building;

    }

    @Override
    public BuildingVo getVoData(Long id) {
        BuildingVo buildingVo = new BuildingVo();

        if (Objects.isNull(id)) {
            return buildingVo;
        }
        Building building = this.getData(id);
        BeanUtils.copyProperties(building, buildingVo);

        // 需要的校区数据
        CampusEasyVo campusEasyVo = campusService.getEasyVoData(buildingVo.getCampusId());
        buildingVo.setCampusEasyVo(campusEasyVo);
        return buildingVo;
    }

    @Override
    public BuildingEasyVo getEasyVoData(Long id) {
        BuildingEasyVo buildingEasyVo = new BuildingEasyVo();

        if (Objects.isNull(id)) {
            return buildingEasyVo;
        }
        Building building = this.getData(id);
        BeanUtils.copyProperties(building, buildingEasyVo);
        return buildingEasyVo;
    }

    @Override
    public PageResult<BuildingVo> queryResultVo(PageQuery pageQuery, QueryParams params) {
        PageResult<BuildingVo> pageResultVo = new PageResult<>();

        SqueryWapper<Building> sQueryWapper = new SqueryWapper<>(Building.class);
        PageResult<Building> pageResult = sQueryWapper.query(this, pageQuery, params);

        // 对象拷贝
        BeanUtils.copyProperties(pageResult, pageResultVo);

        // vo 单独数据获取
        List<BuildingVo> list = new ArrayList<>();
        pageResult.getList().forEach(item-> {

            BuildingVo buildingVo = new BuildingVo();
            BeanUtils.copyProperties(item, buildingVo);

            // 需要的校区数据
            CampusEasyVo campusEasyVo = campusService.getEasyVoData(item.getCampusId());
            buildingVo.setCampusEasyVo(campusEasyVo);
            list.add(buildingVo);
        });

        pageResultVo.setList(list);
        return pageResultVo;
    }

    @Override
    public List<BuildingVo> getListVoByCampusId(QueryParams params) {
        List<BuildingVo> listVo = new ArrayList<>();

        // 架构get 请求参数格式：
//        [name-like~楼栋1, area-like~100]
        List<String> f = params.getF();

        if (0 >= f.size()) {
            return listVo;
        }

        String campusIsStr = f.get(0);

        String[] temp = campusIsStr.split(params.VALUE_JOIN);
        if (1 >= temp.length) {
            return listVo;
        }

        // 院区id
        String campusId = temp[1];
        if (StringUtils.isBlank(campusId)) {
            return listVo;
        }

        List<Building> listT = list(Wrappers.<Building>lambdaQuery().eq(Building::getCampusId, campusId));
        listT.forEach(item-> {
            BuildingVo buildingVo = new BuildingVo();
            BeanUtils.copyProperties(item, buildingVo);
            listVo.add(buildingVo);
        });
        return listVo;
    }

    @Override
    public List<Building> getListByCampusId(QueryParams params) {
        List<Building> list = new ArrayList<>();

        // 架构get 请求参数格式：
//        [name-like~楼栋1, area-like~100]
        List<String> f = params.getF();

        if (0 >= f.size()) {
            return list;
        }

        String campusIsStr = f.get(0);

        String[] temp = campusIsStr.split(params.VALUE_JOIN);
        if (1 >= temp.length) {
            return list;
        }

        // 院区id
        String campusId = temp[1];
        if (StringUtils.isBlank(campusId)) {
            return list;
        }

        list = list(Wrappers.<Building>lambdaQuery().eq(Building::getCampusId, campusId));
        return list;
    }

    @Override
    public FcStatisticsVo getStatistics(Long campusId) {

        FcStatisticsVo fcStatisticsVo = new FcStatisticsVo();

        LambdaQueryWrapper<Building> lambdaQueryWrapper = Wrappers.<Building>lambdaQuery();
        if (!Objects.isNull(campusId)) {
            lambdaQueryWrapper.eq(Building::getCampusId, campusId);
        }
        List<Building> list = this.list(lambdaQueryWrapper);

        if (0 >= list.size()) {
            fcStatisticsVo.setDataCount("0");
            fcStatisticsVo.setDataPlan("0");
            fcStatisticsVo.setDataUse("0");
            return fcStatisticsVo;
        }

        AtomicReference<Float> plan = new AtomicReference<>((float) 0);
        AtomicReference<Float> use = new AtomicReference<>((float) 0);
        list.forEach(item-> {
            if (StringUtils.isNotBlank(item.getArea())) {
                plan.updateAndGet(v -> new Float((float) (v + (Float.parseFloat(item.getArea())))));
            }
            if (StringUtils.isNotBlank(item.getUseArea())) {
                use.updateAndGet(v -> new Float((float) (v + (Float.parseFloat(item.getUseArea())))));
            }
        });

        // 数据总数
        fcStatisticsVo.setDataCount(String.valueOf(list.size()));
        fcStatisticsVo.setDataPlan(String.valueOf(plan.get()));
        fcStatisticsVo.setDataUse(String.valueOf(use.get()));
        return fcStatisticsVo;
    }

    @Override
    public Building getByCampusIdAndName(Long campusId, String name) {

        if (Objects.isNull(campusId) || StringUtils.isBlank(name)) {
            return new Building();
        }
        return this.getFirst(Wrappers.<Building>lambdaQuery().eq(Building::getCampusId, campusId).eq(Building::getName,
         name));
    }

    @Override
    public void exportExcel(String filename, QueryParams params, HttpServletResponse resp) {
        SqueryWapper<Building> squeryWapper = new SqueryWapper<>(Building.class);

        if (null == squeryWapper) {
            squeryWapper = new SqueryWapper<>(Building.class);
        }
        QueryWrapper<Building> wrapper = Wrappers.query();
        squeryWapper.setWhere(params.getF(), wrapper);
        squeryWapper.setSelect(params.getFields(), wrapper);
        squeryWapper.setOrderBy(params.getOrderBy(), wrapper);

        List<Building> list = new ArrayList<>();
        List<BuildingIo> listIo = new ArrayList<>();
        if (null == params.getF()) {
            list.add(new Building());
            listIo.add(new BuildingIo());
        } else {
            list = this.list(wrapper);
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        list.forEach(item->{

            Building building = this.getData(item.getId());

            BuildingIo buildingIo = new BuildingIo();
            BeanUtils.copyProperties(item, buildingIo);
            buildingIo.setCampusName(campusService.getEasyVoData(building.getCampusId()).getName());

            if (null != building.getTypeId()) {
                buildingIo.setTypeName(buildingTypeService.getById(building.getTypeId()).getName());
            }

            String year = "";
            if (null != item.getYears()) {
                year = item.getYears().format(df);
            }
            buildingIo.setYears(year);
            listIo.add(buildingIo);
        });

        if (StringUtils.isBlank(filename)) {
            filename = "楼栋";
        }

        // 导出
        ExcelUtil.exportExcel(filename, listIo, resp);
    }

    @Override
    public HttpResult<Void> importExcel(MultipartFile files) {
        List<BuildingIo> dataList;
        try {
            dataList = EasyExcel.read(files.getInputStream()).head(BuildingIo.class).sheet()
                    .doReadSync();
        } catch (Exception e) {
            return HttpResult.fail("B0000", I18n.build("数据格式存在问题，无法读取！"));
        }
        if (0 >= dataList.size()) {
            return HttpResult.fail("B0000", I18n.build("无数据，无法读取！"));
        }

        AtomicInteger successNum = new AtomicInteger();
        AtomicInteger errorNum = new AtomicInteger();
        dataList.forEach(item-> {
            importExcelHelper(item, successNum, errorNum);
        });

        String message = "总数：" + dataList.size() + "; 成功：" + successNum.get() + "; 失败：" + errorNum.get();
        return HttpResult.success("导入成功 " + message);
    }

    @Override
    public HttpResult<Serializable> updateSort(List<Map<String, Integer>> sortedData) {
        if (null == sortedData || 0 >= sortedData.size()) {
            return HttpResult.fail("4000", "排序数据不可为空", "error");
        }

        sortedData.forEach(item-> {

            if (!item.containsKey("id") || !item.containsKey("orders")) {
                return;
            }

            Long id = item.get("id").longValue();;
            int orders = item.get("orders");

            Building building = new Building();
            building.setId(id);
            building.setOrders(orders);
            this.updateById(building);
        });
        return HttpResult.success("排序成功");
    }

    /**
     * 导入数据帮助类
     * @param buildingIo
     * @param successNum
     * @param errorNum
     */
    private void importExcelHelper(BuildingIo buildingIo, AtomicInteger successNum, AtomicInteger errorNum) {

        String campusName = buildingIo.getCampusName();

        boolean checkFlag =
                StringUtils.isBlank(campusName) || StringUtils.isBlank(buildingIo.getName()) || StringUtils.isBlank(buildingIo.getArea()) || StringUtils.isBlank(buildingIo.getUseArea()) || null == (buildingIo.getGroundFloor()) || StringUtils.isBlank(buildingIo.getGroundArea()) || null == (buildingIo.getUndergroundFloor()) || StringUtils.isBlank(buildingIo.getUndergroundArea()) || StringUtils.isBlank(buildingIo.getYears()) || !BuildingValidation.checkAccounts(buildingIo.getAccountsSituation()) || StringUtils.isBlank(buildingIo.getTypeName());

        if (checkFlag) {
            errorNum.getAndIncrement();
            return;
        }

        Building building = new Building();
        BeanUtils.copyProperties(buildingIo, building);

        Campus campus = campusService.getByName(campusName);
        if (null == (campus) && Objects.isNull(campus.getId())) {
            errorNum.getAndIncrement();
            return;
        }
        building.setCampusId(campus.getId());

        building.setParentId(building.getCampusId() + "-0-0-0");

        try {

            BuildingType buildingType = buildingTypeService.getByName(buildingIo.getTypeName());

            if (null != buildingType) {
                building.setTypeId(buildingType.getId());
            }

            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            building.setYears(LocalDate.parse(buildingIo.getYears(), df));

            this.save(building);
            successNum.getAndIncrement();
        } catch (Exception e) {
            e.printStackTrace();
            errorNum.getAndIncrement();
            return;
        }
    }
}
